package logic

import (
	"core/command"
	"core/common"
	"core/component/logger"
	"core/component/router"
	"sync"
)

var (
	world *World
)

type World struct {
	players           sync.Map
	msgChannel        chan *common.PlayerMsgData
	roomSrv           *RoomSrv
	pvps              *PvpPools
	router            *router.Router
	chanPlayerOffline chan uint64
	playerChanMsg     chan *common.PlayerMsgData
	stop              chan int
	addPlayerChan     chan interface{}
	removePlayerChan  chan uint64
}

func (w *World) Init(processId int) {
	world = &World{
		msgChannel:        make(chan *common.PlayerMsgData, 128*1024),
		chanPlayerOffline: make(chan uint64, 128*1024),
		playerChanMsg:     make(chan *common.PlayerMsgData, 128*1024),
		addPlayerChan:     make(chan interface{}, 128*1024),
		removePlayerChan:  make(chan uint64, 1),
		roomSrv:           newRoomSrv(processId),
		pvps:              NewPvpPools(),
		router:            router.NewRouter(),
		stop:              make(chan int, 1),
	}
	world.registerWorldHandler()
	go world.loop()
}

func WorldGetMe() *World {
	return world
}

func (w *World) getPlayer(playerId uint64) *Player {
	if value, ok := w.players.Load(playerId); ok {
		return value.(*Player)
	}
	return nil
}

func (w *World) addPlayer(pInfo *command.PlayerIntoPvpServer) {
	if p, ok := w.players.Load(pInfo.PlayerId); !ok {
		player := newPlayer(pInfo)
		w.players.Store(pInfo.PlayerId, player)
		logger.Infof("玩家(%v)进入pvpWorld online-->pvp", pInfo.PlayerId)
	} else {
		player, exist := p.(*Player)
		if exist {
			player.nickName = pInfo.NickName
		}
	}
	return
}

func (w *World) removePlayer(playerId uint64) {
	p, ok := world.players.Load(playerId)
	if !ok {
		return
	}

	player, ok := p.(*Player)

	if !ok {
		return
	}

	world.players.Delete(player.playerId)

	player = nil
	logger.Infof("玩家(%v)移除pvpWorld", playerId)
}

func (w *World) loop() {
	for {
		select {
		case msg := <-w.msgChannel:
			w.onMessage(msg)
		case playerId := <-w.chanPlayerOffline:
			w.doPlayerOffline(playerId)
		case msg := <-w.playerChanMsg:
			w.doPlayerChanData(msg)
		case msg := <-w.addPlayerChan:
			w.addPlayer(msg.(*command.PlayerIntoPvpServer))
		case id := <-w.removePlayerChan:
			w.removePlayer(id)
		case <-w.stop:
			return
		}
	}
}

func (world *World) doPlayerChanData(msg *common.PlayerMsgData) {
	player := world.getPlayer(msg.PlayerID)
	if player == nil {
		return
	}
	player.addPlayerMsgChannel(msg.Data)
}

func (world *World) doPlayerOffline(playerId uint64) {
	player := world.getPlayer(playerId)
	if player == nil {
		return
	}
	pl, ok := world.pvps.pools[player.score]
	if ok {
		pl.removePvpPool(player)
	}
	if player.roomId != 0 {
		world.roomSrv.playerLeave(player.roomId, player.playerId)
	}
	player.handleOfflineOP()
}

func (world *World) onMessage(msg *common.PlayerMsgData) {
	msgID, err := world.router.Route(msg.Data)
	if err == nil {
		logger.Infof("消息路由到world cmd:%v", command.Command(msgID).String())
		return
	}
	world.roomSrv.sendMsgToRoomSrv(msg)
}

func (world *World) FinializeSave() {
	world.stop <- 1
	world.roomSrv.stop <- 1
}

func (world *World) sendRemovePlayer(id uint64) {
	world.removePlayerChan <- id
}
